﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using Ordinaire.Data;
using Ordinaire.Db;

namespace Ordinaire
{
    /// <summary>
    /// Represents a common data manager that provides common functions on referential data structure.
    /// </summary>
    /// <remarks>This currently only supports type int and string as its id and creator/updator respectively</remarks>
    public class ReferenceDataManager<TOContext> : DataManager<TOContext>
        where TOContext : OContext
    {
        /// <summary>
        /// Returns list of data matches with the specified foreign id.
        /// </summary>
        /// <typeparam name="TTable">type of table</typeparam>
        /// <typeparam name="TForeign">type of foreign table</typeparam>
        /// <typeparam name="TId">type of data unique identifier</typeparam>
        /// <typeparam name="TWho">type of data IAudit</typeparam>
        /// <param name="id">the foreign id</param>
        /// <returns>list of data matches with the specified foreign id</returns>
        public List<TTable> GetAllByForeignId<TTable, TForeign, TId, TWho>(TId id)
            where TTable   : ReferenceData<TForeign, TId, TWho>
            where TForeign : Data<TId, TWho>
        {
            return Context
                .GetTable<TTable>()
                .Where(d => d.ForeignId.Equals(id))
                .ToList();
        }

        /// <summary>
        /// Returns data matches with the specified foreign id.
        /// </summary>
        /// <typeparam name="TTable">type of table</typeparam>
        /// <typeparam name="TForeign">type of foreign table</typeparam>
        /// <typeparam name="TId">type of data unique identifier</typeparam>
        /// <typeparam name="TWho">type of data IAudit</typeparam>
        /// <param name="id">the foreign id</param>
        /// <returns>data matches with the specified foreign id</returns>
        public TTable GetByForeignId<TTable, TForeign, TId, TWho>(TId id)
            where TTable   : ReferenceData<TForeign, TId, TWho>
            where TForeign : Data<TId, TWho>
        {
            return Context
                .GetTable<TTable>()
                .Where(d => d.ForeignId.Equals(id))
                .SingleOrDefault();
        }

        /// <summary>
        /// Returns the associated/foreign data with the id of current data.
        /// </summary>
        /// <typeparam name="TTable">type of table</typeparam>
        /// <typeparam name="TForeign">type of foreign table</typeparam>
        /// <typeparam name="TId">type of data unique identifier</typeparam>
        /// <typeparam name="TWho">type of data IAudit</typeparam>
        /// <param name="id">the id</param>
        /// <returns>the associated/foreign data with the id of current data</returns>
        public List<TForeign> GetForeignsById<TTable, TForeign, TId, TWho>(TId id)
            where TTable   : ReferenceData<TForeign, TId, TWho>
            where TForeign : Data<TId, TWho>
        {
            return Context
                .GetTable<TTable>()
                .Where(d => d.Id.Equals(id))
                .Select(d => d.Foreign)
                .ToList();
        }

        /// <summary>
        /// Returns the associated/foreign data with the specified foreign id.
        /// </summary>
        /// <typeparam name="TTable">type of table</typeparam>
        /// <typeparam name="TForeign">type of foreign table</typeparam>
        /// <typeparam name="TId">type of data unique identifier</typeparam>
        /// <typeparam name="TWho">type of data IAudit</typeparam>
        /// <param name="id">the foreign id</param>
        /// <returns>the associated/foreign data with the id of current data</returns>
        public List<TForeign> GetForeignsByForeignId<TTable, TForeign, TId, TWho>(TId id)
            where TTable   : ReferenceData<TForeign, TId, TWho>
            where TForeign : Data<TId, TWho>
        {
            return Context
                .GetTable<TTable>()
                .Where(d => d.ForeignId.Equals(id))
                .Select(d => d.Foreign)
                .ToList();
        }
    }
}
